import random
import gc
import pygame
import math
from pygame import *
from pygui import *
from ezpygui import *
from pyconsole import *
import time
import datetime
import EasyXML
from EasyDebugger import *
import crumbs
import stdtags
import question

pygame.init()

WRONG_ANSWER_DELAY = 1.5

class Game(watched):
    #called when the game is initialized
    #called when the game is initialized
    def __init__(self):
        #make the screen buffer
        self.status = ""
        self.correct = 0
        self.total = 0
        self.starttime = None
        self.endtime = None
        self.playloop = 0
        self.realmult = "x1.0"
        self.screen = pygame.display.set_mode((800,600))

        #make a background buffer
        self.bg = pygame.Surface((800, 600)).convert()
        self.bg.fill((225, 225, 255))
        
        self.dtime = 0;

        #create a default font
        self.font = pygame.font.Font(None, 16)

        #this is the code I wrote before: handles the GUI and in-game console
        wmgr.setup(self.screen)
        command.setup(self.screen)

        #initialize game
        self.loadPlayers()
        self.curPlayer = 1
        
        self.score = 0
        self.mult = 0
        
        #define the main menu
        self.mmenu = window("MainMenu")
        wmgr.add(self.mmenu)
        titleImg = wimage("title", "title.png")
        titleImg.rect.top = 150
        startButton = wimgbutton("start", "startbtn.png", self.startClicked) #make a play button
        startButton.rect.top = 300
        progressButton = wimgbutton("progress", "progressbtn.png" , self.progressClicked)
        progressButton.rect.top = 350
        instructButton = wimgbutton("instruct", "instrbtn.png", self.instructClicked)
        instructButton.rect.top = 400
        setupButton = wimgbutton("setup", "brainbtn.png", self.setupClicked)
        setupButton.rect.top = 450
        leaveButton = wimgbutton("leave", "exitbtn.png", self.leaveClicked)
        leaveButton.rect.top = 500

        self.mmenu.align(ALIGN_CENTER)
        self.mmenu.add(titleImg)
        titleImg.align(ALIGN_CENTER)
        self.mmenu.add(startButton)    #add start menu to the GUI 
        startButton.align(ALIGN_CENTER)
        self.mmenu.add(progressButton)
        progressButton.align(ALIGN_CENTER)
        self.mmenu.add(instructButton)
        instructButton.align(ALIGN_CENTER)
        self.mmenu.add(setupButton)
        setupButton.align(ALIGN_CENTER)
        self.mmenu.add(leaveButton)
        leaveButton.align(ALIGN_CENTER)
        
        #define the playing field
        self.playfield = window("PlayField", Rect(50,50,700,500))
        wmgr.add(self.playfield)
        self.playfield.visible = 0
        
        self.scores = window("Scores", Rect(685, 0, 0, 400))
        self.playfield.add(self.scores)
        self.bottom = window("bottom", Rect(50, 425, 550, 0))
        self.playfield.add(self.bottom)
        
        self.brainbar = whealth("brainbar", "FullBar.png", "EmptyBar.png", 1000, 1)
        self.brainbar.health = 0
        self.scores.add(self.brainbar)
        self.brainbar.align(ALIGN_BOTTOMCENTER)
        self.scoretxt = wvartext("scoretxt", self, "score", color=(0,0,0))
        self.scores.add(self.scoretxt)
        self.scoretxt.align(ALIGN_CENTER)
        self.scoretxt.rect.top = 150
        self.scoretxtm = wvartext("scoretxtm", self, "realmult", color=(0,0,0))
        self.scores.add(self.scoretxtm)
        self.scoretxtm.align(ALIGN_CENTER)
        self.scoretxtm.rect.top = 120
        self.timer = wtxtbutton("timer", "greenbtn.png", "0m")
        self.timer.image.disabled = 2
        self.bottom.add(self.timer)
        self.timer.align(ALIGN_CENTER)
        self.timer2 = wtxtbutton("timer2", "mathbtn_y.png", "0m")
        self.timer2.image.disabled = 2
        self.bottom.add(self.timer2)
        self.timer2.align(ALIGN_RIGHT)
        
        self.home = wimgbutton("home", "home.png", self.puzzleHomeClicked)
        self.bottom.add(self.home)
        self.progress = wimgbutton("progress", "progress.png", self.progressClicked)
        self.bottom.add(self.progress)
        self.progress.rect.left = 50
        
        
        puzzle = wimage("Puzzle" + str(random.random()), "puzzle.png")
        
        
        ####################3
        # Parse the question XML
        story = EasyXML.getXML("parsetest.xml")
        self.root = EasyXML.parseXML(story.documentElement)
        self.parser = crumbs.CrumbParser()
        stdtags.register(self.parser)
        question.register(self.parser, self.playfield)
        
        self.parser.puzzle = puzzle
        self.playfield.add(self.parser.puzzle)
        self.parser.puzzle.align(ALIGN_CENTER)
     
        #define the instructions menu
        self.imenu = window("instructMenu")
        wmgr.add(self.imenu)
        self.imenu.visible = 0
        titleImg = wimage("instruct_title", "title.png")
        titleImg.rect.top = 50
        backButton = wtxtbutton("backButton", "redbtn.png", "Back", self.backClicked)
        backButton.rect.top = 450
        menuButton = wtxtbutton("menuButton", "redbtn.png", "Menu", self.menuClickedI)
        menuButton.rect.top = 450
        forwardButton = wtxtbutton("forwardButton", "greenbtn.png", "Forward", self.forwardClicked)
        forwardButton.rect.top = 450
     
        self.instruct = 1
        instructImg = wimage("instructions", "instructions1.bmp")
        instructImg.rect.top = 100
    
        self.imenu.align(ALIGN_CENTER)
        self.imenu.add(titleImg)
        titleImg.align(ALIGN_CENTER)
        self.imenu.add(instructImg)
        instructImg.align(ALIGN_CENTER)
        self.imenu.add(backButton)
        backButton.rect.left = -375
        self.imenu.add(menuButton)
        menuButton.rect.left = -150
        self.imenu.add(forwardButton)
        forwardButton.rect.left = 100
        
        #define the progress menu
        self.pmenu = window("progressMenu")
        wmgr.add(self.pmenu)
        self.pmenu.visible = 0
        titleImg = wtext("statistics", "Statistics")
        titleImg.rect.top = 50
        
        correctImg = wtext("correctImg", "Correct:")
        correctImg.rect.top = 200
        
        timeImg = wtext("timeImg", "Time:")
        timeImg.rect.top = 250
        
        menuButton = wtxtbutton("menuButton", "redbtn.png", "Menu", self.menuClickedP)
        menuButton.rect.top = 450
        startButton = wtxtbutton("startButton", "greenbtn.png", "Start", self.progStartClicked)
        startButton.rect.top = 450

        self.pmenu.align(ALIGN_CENTER)
        self.pmenu.add(titleImg)
        titleImg.align(ALIGN_CENTER)
        self.pmenu.add(correctImg)
        correctImg.align(ALIGN_RIGHT)
        self.pmenu.add(timeImg)
        timeImg.align(ALIGN_RIGHT)
        self.pmenu.add(menuButton)
        menuButton.rect.left = -300
        self.pmenu.add(startButton)
        
        #define the setup menu
        self.smenu = window("setupMenu")
        wmgr.add(self.smenu)
        self.smenu.visible = 0
        titleImg = wimage("setup", "title.png")
        titleImg.rect.top = 50
        SelectAButton = wtxtbutton("selectA", "greenbtn.png", "Player 1", self.SelectAClicked)
        SelectAButton.rect.top = 200
        SelectBButton = wtxtbutton("selectB", "greenbtn.png", "Player 2", self.SelectBClicked)
        SelectBButton.rect.top = 250
        SelectCButton = wtxtbutton("selectC", "greenbtn.png", "Player 3", self.SelectCClicked)
        SelectCButton.rect.top = 300
        SelectDButton = wtxtbutton("selectD", "greenbtn.png", "Player 4", self.SelectDClicked)
        SelectDButton.rect.top = 350
        NewAButton = wtxtbutton("playerA", "greenbtn.png", "Create New", self.NewAClicked) 
        NewAButton.rect.top = 200
        NewBButton = wtxtbutton("playerBButton", "greenbtn.png" , "Create New", self.NewBClicked)
        NewBButton.rect.top = 250
        NewCButton = wtxtbutton("playerCButton", "greenbtn.png", "Create New", self.NewCClicked)
        NewCButton.rect.top = 300
        NewDButton = wtxtbutton("playerDButton", "greenbtn.png", "Create New", self.NewDClicked)
        NewDButton.rect.top = 350
        
        setupMenuButton = wimgbutton("setupMenu", "exitbtn.png", self.setupMenuClicked)
        setupMenuButton.rect.top = 400

        self.smenu.align(ALIGN_CENTER)
        self.smenu.add(titleImg)
        titleImg.align(ALIGN_CENTER)
        
        self.smenu.add(SelectAButton)            
        SelectAButton.align(ALIGN_RIGHT)
        self.smenu.add(SelectBButton)     
        SelectBButton.align(ALIGN_RIGHT)
        self.smenu.add(SelectCButton)     
        SelectCButton.align(ALIGN_RIGHT)
        self.smenu.add(SelectDButton)     
        SelectDButton.align(ALIGN_RIGHT)
        
        self.smenu.add(NewAButton)     
        NewAButton.align(ALIGN_LEFT)
        self.smenu.add(NewBButton)
        NewBButton.align(ALIGN_LEFT)
        self.smenu.add(NewCButton)
        NewCButton.align(ALIGN_LEFT)
        self.smenu.add(NewDButton)
        NewDButton.align(ALIGN_LEFT)
        
        self.smenu.add(setupMenuButton)
        setupMenuButton.align(ALIGN_CENTER)
        
    def loadPlayers(self):
        file = open('playerSetup.txt', 'r')
    
        self.p1 = file.readline()[:-1]
        self.p1avg = int(file.readline()[:-1])
        self.p1time = int(file.readline()[:-1])
        self.p2 = file.readline()[:-1]
        self.p2avg = int(file.readline()[:-1])
        self.p2time = int(file.readline()[:-1])
        self.p3 = file.readline()[:-1]
        self.p3avg = int(file.readline()[:-1])
        self.p3time = int(file.readline()[:-1])
        self.p4 = file.readline()[:-1]
        self.p4avg = int(file.readline()[:-1])
        self.p4time = int(file.readline())
        
    def savePlayers(self):
        file = open('playerSetup.txt', 'w')
        
        file.write(self.p1)
        file.write('\n')
        s=str(self.p1avg)
        file.write(s)
        file.write('\n')
        s=str(self.p1time)
        file.write(s)
        file.write('\n')
        
        file.write(self.p2)
        file.write('\n')
        s=str(self.p2avg)
        file.write(s)
        file.write('\n')
        s=str(self.p2time)
        file.write(s)
        file.write('\n')
        
        file.write(self.p3)
        file.write('\n')
        s=str(self.p3avg)
        file.write(s)
        file.write('\n')
        s=str(self.p3time)
        file.write(s)
        file.write('\n')
        
        file.write(self.p4)
        file.write('\n')
        s=str(self.p4avg)
        file.write(s)
        file.write('\n')
        s=str(self.p4time)
        file.write(s)
      
        file.close()

    #display the main menu
    def MainMenu(self):
        while True: #loop until we break out manually.
            #get events.
            for event in pygame.event.get():
                #pass events to GUI
                wmgr.injectEvent(event)

                if event.type == QUIT:
                    sys.exit()
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        sys.exit()
                    elif event.key == K_BACKQUOTE:
                        ret = command.showConsole(globals(), locals())
                        if ret is 0:
                            sys.exit()

            #blit the background to the screen, blanking it
            self.screen.blit(self.bg, (0, 0))
            wmgr.draw()

            pygame.display.flip()


    def showPuzzle(self):
        print "Showing next puzzle..."
        self.status = "puzzle"
        self.parser.puzzle.num = 0 #for correct use with the XML, records how many child elements there are
        self.parser.puzzle.answerlists = []
        
        
        self.parser.parseCrumb(self.root, True)
        
        dtime = time.localtime()
        self.puzzletime = datetime.datetime(dtime[0], dtime[1], dtime[2], dtime[3], dtime[4], dtime[5])

        
        while True: #loop until we break out manually.
            if self.status == "mmenu":
                return False
            done = True
            import gc
            for list in self.parser.puzzle.answerlists:
                if list.answered == False:
                    done = False
                    break
            if done == True:
                break
            
                #probably do something more here shortly.
                
            #get events.
            for event in pygame.event.get():
                #pass events to GUI
                wmgr.injectEvent(event)

                if event.type == QUIT:
                    sys.exit()
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        sys.exit()
                    elif event.key == K_BACKQUOTE:
                        ret = command.showConsole(globals(), locals())
                        if ret is 0:
                            sys.exit()

            #update the timer displays
            dtime = time.localtime()
            now = datetime.datetime(dtime[0], dtime[1], dtime[2], dtime[3], dtime[4], dtime[5])
            delta = now - self.starttime
            minutes, seconds = divmod(delta.seconds, 60)
            hours, minutes = divmod(minutes, 60)
            
            out = ""
            if hours > 0:
                out += str(hours) + "h "
            out += str(minutes) + "m " + str(seconds) + "s"
            
            self.timer.text.setText(out)
            
            delta = now - self.puzzletime
            
            out = str(delta.seconds) + "s"
            
            self.timer2.text.setText(out)
            
            #blit the background to the screen, blanking it
            self.screen.blit(self.bg, (0, 0))
            wmgr.draw()

            pygame.display.flip()
            
        
        correct = True
        for al in self.parser.puzzle.answerlists:
            print al.answered, al.correct_parsed
            if al.answered != al.correct_parsed:
                correct = False
                break
        
        if correct:
            print "Correct!"
            self.score += int(0.02 * self.mult) + 5
            self.realmult = "x" + str(math.floor(((0.02 * self.mult) / 5.0 + 1.0) * 100.0) / 100.0)
            chmult = (1000 - self.mult) * 0.1
            self.mult += chmult
            self.correct += 1
        else:
            chmult = self.mult * 0.1 + 5
            self.mult -= chmult
            for al in self.parser.puzzle.answerlists:
                for answer in al.answers:
                    if answer.answer.id != al.correct_parsed:
                        answer.disabled = 1
                    else:
                        answer.disabled = 2
                        
            timer = WRONG_ANSWER_DELAY
            clock = pygame.time.Clock()
            while timer > 0.0:
                if self.status == "mmenu":
                    return False
                for event in pygame.event.get():
                    #pass events to GUI
                    wmgr.injectEvent(event)
    
                    if event.type == QUIT:
                        sys.exit()
                    if event.type == KEYDOWN:
                        if event.key == K_ESCAPE:
                            sys.exit()
                        elif event.key == K_BACKQUOTE:
                            ret = command.showConsole(globals(), locals())
                            if ret is 0:
                                sys.exit()
                        if event.key == K_n:
                            timer = 0.0
                            
                self.screen.blit(self.bg, (0, 0))
                wmgr.draw()
    
                pygame.display.flip()
                clock.tick(20)
                timer -= 0.05
                           
        self.total += 1       
        
        return True
        
    def PlayLoop(self):
        self.playfield.visible = 1
        self.playloop = 1
        
        
        dtime = time.localtime()
        temp = datetime.datetime(dtime[0], dtime[1], dtime[2], dtime[3], dtime[4], dtime[5])
            
        if self.starttime is None:
            self.starttime = temp
        else:
            self.starttime += temp - self.endtime
        
        while self.showPuzzle():
            gc.collect()
            self.parser.puzzle.clear()
            if self.mult > 1000:
                self.mult = 1000
            elif self.mult < 0:
                self.mult = 0
                
            self.brainbar.health = self.mult
            print self.mult, self.brainbar.max
            
        dtime = time.localtime()
        self.endtime = datetime.datetime(dtime[0], dtime[1], dtime[2], dtime[3], dtime[4], dtime[5])
            
        self.parser.puzzle.clear()
            
        self.playfield.visible = 0
        
        self.mmenu.visible = 1
        self.playloop = 0
        wmgr.add(self.mmenu)
        
    def startClicked(self, window, pos, button):
        self.mmenu.visible = 0
        self.PlayLoop()
        
    def progressClicked(self, window, pos, button):
        dtime = time.localtime()
        self.endtime = datetime.datetime(dtime[0], dtime[1], dtime[2], dtime[3], dtime[4], dtime[5])
         
        wmgr.remove("MainMenu")
        self.pmenu.remove("correctText")
        self.pmenu.remove("timeText")
        self.pmenu.visible = 1
        self.playfield.visible = 0
        #if self.curPlayer == 1:
#            correct = self.p1avg
#            time = self.p1time
#        if self.curPlayer == 2:
#            correct = self.p2avg
#            time = self.p2time
#        if self.curPlayer == 3:
#            correct = self.p3avg
#            time = self.p3time
#        if self.curPlayer == 4:
#            correct = self.p4avg
#            time = self.p4time
        if self.total:
            print "calc percent"
            percent = int((float(self.correct) / float(self.total)) * 100.0)
        else:
            percent = 0
        
        correctText = wtext("correctText", " " + str(self.correct) + " out of " + str(self.total) + " (" + str(percent) + "%)")
        correctText.rect.top = 200
        if self.starttime:
            delta = self.endtime - self.starttime
            timeText = wtext("timeText", " " + str(delta) + " (" + str(float(delta.seconds) / float(self.total)) + "s average each)")
        else:
            timeText = wtext("timeText", " None")
        timeText.rect.top = 250
        
        self.pmenu.add(correctText)
        correctText.align(ALIGN_LEFT)
        self.pmenu.add(timeText)
        correctText.align(ALIGN_LEFT)
        
               
    def instructClicked(self, window, pos, button):
        wmgr.remove("MainMenu")
        self.imenu.visible = 1
        
    def setupClicked(self, window, pos, button):
        wmgr.remove("MainMenu")
        self.smenu.visible = 1
    
    def leaveClicked(self, window, pos, button):
        sys.exit()
        
    def menuClickedP(self, window, pos, button):
        self.pmenu.visible = 0
        
        if self.playloop is not 1:
            wmgr.add(self.mmenu)
        else:
            self.status = "mmenu"
    
    def progStartClicked(self, window, pos, button):
        self.pmenu.visible = 0
        
        if self.playloop is not 1:
            self.PlayLoop()
        else:
            print "resuming"
            dtime = time.localtime()
            temp = datetime.datetime(dtime[0], dtime[1], dtime[2], dtime[3], dtime[4], dtime[5])
         
            self.playfield.visible = 1
            self.starttime += temp - self.endtime
            self.puzzletime += temp - self.endtime

    def backClicked(self, window, pos, button):
        if self.instruct > 1:
            self.instruct = self.instruct - 1
            iImg = "instructions" + str(self.instruct) + ".bmp"
            instructImg = wimage("instructions", iImg)
            instructImg.rect.top = 100
            self.imenu.remove("instructions")
            self.imenu.add(instructImg)
            instructImg.align(ALIGN_CENTER)
            
 
    def forwardClicked(self, window, pos, button):
        if self.instruct < 6:
            self.instruct = self.instruct + 1
            iImg = "instructions" + str(self.instruct) + ".bmp"
            instructImg = wimage("instructions", iImg)
            instructImg.rect.top = 100
            self.imenu.remove("instructions")
            self.imenu.add(instructImg)
            instructImg.align(ALIGN_CENTER)
            

    def menuClickedI(self, window, pos, button):
        self.imenu.visible = 0
        wmgr.add(self.mmenu)
        
    def SelectAClicked(self, window, pos, button):
        self.curPlayer = 1
    
    def SelectBClicked(self, window, pos, button):
        self.curPlayer = 2
    
    def SelectCClicked(self, window, pos, button):
        self.curPlayer = 3
        
    def SelectDClicked(self, window, pos, button):
        self.curPlayer = 4
        
    def NewAClicked(self, window, pos, button):
        box = TextBox("Please enter a name:")
        self.p1 = box.ask(self.screen)
        self.p1avg = 0
        self.p1time = 0
        self.savePlayers()
        self.smenu.remove("APlayer")
        NameAPlayer = wtext("APlayer", self.p1)
        NameAPlayer.rect.top = 200
        
        self.smenu.add(NameAPlayer)
        NameAPlayer.align(ALIGN_RIGHT)
        
    def NewBClicked(self, window, pos, button):
        box = TextBox("Please enter a name:")
        self.p2 = box.ask(self.screen)
        self.p2avg = 0
        self.p2time = 0
        self.savePlayers()
        self.smenu.remove("BPlayer")
        NameBPlayer = wtext("BPlayer", self.p2)
        NameBPlayer.rect.top = 250
        
        self.smenu.add(NameBPlayer)
        NameBPlayer.align(ALIGN_RIGHT)
    
    def NewCClicked(self, window, pos, button):
        print " C clicked"
        box = TextBox("Please enter a name:")
        self.p3 = box.ask(self.screen)
        self.p3avg = 0
        self.p3time = 0
        self.savePlayers()
        self.smenu.remove("CPlayer")
        NameCPlayer = wtext("CPlayer", self.p3)
        NameCPlayer.rect.top = 300
        
        self.smenu.add(NameCPlayer)
        NameCPlayer.align(ALIGN_RIGHT)
    
    def NewDClicked(self, window, pos, button):
        print " D clicked"
        box = TextBox("Please enter a name:")
        self.p4 = box.ask(self.screen)
        self.p4avg = 0
        self.p4time = 0
        self.savePlayers()
        self.smenu.remove("DPlayer")
        NameDPlayer = wtext("DPlayer", self.p4)
        NameDPlayer.rect.top = 350
        
        self.smenu.add(NameDPlayer)
        NameDPlayer.align(ALIGN_RIGHT)
        
    def setupMenuClicked(self, window, pos, button):
        print "setupMenuClicked"
        self.smenu.visible = 0
        wmgr.add(self.mmenu)
        
    def puzzleHomeClicked(self, window, pos, button):
        self.status = "mmenu"
        
        
#create an instance of the game
game = Game()

#start the main menu
game.MainMenu()

